package com.guinea.core.service;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.guinea.core.Constants;
import com.guinea.core.orm.BaseEntity;
import com.guinea.core.orm.HibernateDao;
import com.guinea.core.orm.Page;
import com.guinea.core.utils.BeanUtils;
import com.guinea.core.utils.CommonUtils;

public abstract class EntityService {
	protected Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 重载的Service中不可使用该方法
	 * 
	 * @return
	 */
	public abstract HibernateDao getEntityDao();

	public Object get(Serializable id) {
		return getEntityDao().get(id);
	}

	public List getAll() {
		return getEntityDao().getAll();
	}

	public List get() {
		return getEntityDao().findBy(Constants.STATUS_PROPERTY,
				Constants.STATUS_VALID);
	}

	public void save(Object entity) {
		BaseEntity baseEntity = (BaseEntity) entity;
		Long id = baseEntity.getId();
		if (id == null) {
			baseEntity.setAuthor(CommonUtils.getCurrentUserId());
			baseEntity.setCreated(new Date());
			baseEntity.setStatus(Constants.STATUS_VALID);
		} else {
			baseEntity.setModificator(CommonUtils.getCurrentUserId());
			baseEntity.setUpdated(new Date());
			//在一对一关联中，自动恢复被标记删除的子对像
			if(Constants.STATUS_INVALID.equals(baseEntity.getStatus())){
				baseEntity.setStatus(Constants.STATUS_VALID);
				baseEntity.setAuthor(CommonUtils.getCurrentUserId());
				baseEntity.setCreated(new Date());
			}
		}
		getEntityDao().save(baseEntity);
	}

	// 标记删除,级联删除
	public void erase(Object entity) {
		if (entity == null)
			return;
		ClassMetadata meta = getEntityDao().getSessionFactory()
				.getClassMetadata(entity.getClass());
		String[] ns = meta.getPropertyNames();
		for (int i = 0; i < ns.length; i++) {
			String name = ns[i];
			Type t = meta.getPropertyType(name);
			try {
				if (t.isCollectionType()) {
					Collection c = (Collection) BeanUtils.forceGetProperty(
							entity, name);
					if (c != null && c.size() > 0)
						for (Iterator iter = c.iterator(); iter.hasNext();) {
							erase(iter.next());
						}
				}
				if (t.isEntityType() && t instanceof OneToOneType) {
					Object o = BeanUtils.forceGetProperty(entity, name);
					erase(o);
				}
			} catch (Exception e) {
				logger.error("missing property " + name
						+ " when erasing entity,error:", e);
			}
		}
		BaseEntity baseEntity = (BaseEntity) entity;
		baseEntity.setStatus(Constants.STATUS_INVALID);
		baseEntity.setModificator(CommonUtils.getCurrentUserId());
		baseEntity.setUpdated(new Date());
		getEntityDao().save(baseEntity);
	}

	public void eraseAll(Collection collection) {
		if (collection != null)
			for (Iterator iter = collection.iterator(); iter.hasNext();) {
				erase(iter.next());
			}
	}

	public void delete(Object entity) {
		getEntityDao().delete(entity);
	}

	public Page findPage(final Page page, final List filters) {
		// 设置默认排序方式
		if (!page.isOrderBySetted()) {
			page.setOrderBy(getEntityDao().getIdName());
			page.setOrder(Page.ASC);
		}
		filters.add(Constants.DEFAULT_PROPERTY_FILTER);
		return getEntityDao().findPage(page, filters);
	}

	public List find(final List filters) {
		filters.add(Constants.DEFAULT_PROPERTY_FILTER);
		return getEntityDao().find(filters);
	}

}
